package com.springboot.framework.mvc.mapper.driver;

import com.google.common.base.CaseFormat;
import com.springboot.framework.exception.BaseException;
import com.springboot.framework.mvc.mapper.annotation.*;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class DriverResolver implements BaseResolverInterface {

    static final String tablePattern = "\\$\\{table\\}";

    static final String idPattern = "\\$\\{id\\}";

    static final String columnsPattern = "\\$\\{columns\\}";

    static final String keysPattern = "\\$\\{keys\\}";

    static final String valuesPattern = "\\$\\{values\\}";

    static final String setsPattern = "\\$\\{sets\\}";

    static final String conditionPattern = "\\$\\{conditions\\}";

    /**
     * 判断是否是select方法
     * @param script
     * @return
     */
    public boolean isSelect(String script){
        Matcher matcher = Pattern.compile("[selectSELECT]{6}").matcher(script);
        /* 判断是否是select方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断是否是插入语句
     * @param script
     * @return
     */
    public boolean isInsert(String script){
        Matcher matcher = Pattern.compile("[insertINSERT]{6}").matcher(script);
        /* 判断是否是insert方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断是否更新语句
     * @param script
     * @return
     */
    public boolean isUpdate(String script){
        Matcher matcher = Pattern.compile("[updateUPDATE]{6}").matcher(script);
        /* 判断是否是update方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断是否是删除语句
     * @param script
     * @return
     */
    public boolean isDelete(String script){
        Matcher matcher = Pattern.compile("[deleteDELETE]{6}").matcher(script);
        /* 判断是否是delete方法 */
        if(matcher.find()){
            return true;
        } else{
            return false;
        }
    }

    /**
     * 判断sql是否含有 ${table}
     * @param script
     * @return
     */
    public boolean hasTable(String script){
        Matcher matcher = Pattern.compile(tablePattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${id}
     * @param script
     * @return
     */
    public boolean hasId(String script){
        Matcher matcher = Pattern.compile(idPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${columns}
     * @param script
     * @return
     */
    public boolean hasColumns(String script){
        Matcher matcher = Pattern.compile(columnsPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${keys}
     * @param script
     * @return
     */
    public boolean hasKeys(String script){
        Matcher matcher = Pattern.compile(keysPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${values}
     * @param script
     * @return
     */
    public boolean hasValues(String script){
        Matcher matcher = Pattern.compile(valuesPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断sql是否含有 ${sets}
     * @param script
     * @return
     */
    public boolean hasSets(String script){
        Matcher matcher = Pattern.compile(setsPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 判断是否是条件查询
     * @param script
     * @return
     */
    public boolean hasConditions(String script){
        Matcher matcher = Pattern.compile(conditionPattern).matcher(script);
        return matcher.find();
    }

    /**
     * 获取mapper接口的泛型
     * @param mapperClass
     * @return
     */
    public Class<?> getMapperGenerics(Class<?> mapperClass){
        /*获取mapperClass接口的类型*/
        Type[] types =  mapperClass.getGenericInterfaces();

        ParameterizedType parameterizedType = (ParameterizedType)types[0];
        Type[] types1 = parameterizedType.getActualTypeArguments();
        return (Class<?>)types1[0];

        /* 多个泛型需要遍历 */
        /*Class<?>[]  classes = new Class[types.length];
        for(Type type:types){
            ParameterizedType parameterizedType = (ParameterizedType)type;
            Type[] types1 = parameterizedType.getActualTypeArguments();
            classes[0] = (Class<?>) types1[0];
        }
        return classes;*/
    }

    /**
     * 获取实体类所有的属性
     * @param generics
     * @return
     */
    public List<Field> getFieldList(Class<?> generics){
        /* 获取所有的字段 */
        //获取所有属性的合集
        List<Field> fieldList = new ArrayList();
        /* 判断是否有该注解 */
        if(generics.isAnnotationPresent(UseParent.class)){
            /* 添加父类的所有字段 */
            fieldList.addAll(Arrays.asList(generics.getSuperclass().getDeclaredFields()));
        }
        /* 添加本类所有字段 */
        fieldList.addAll(Arrays.asList(generics.getDeclaredFields()));
        return fieldList;
    }

    /**
     * 替换insert与update的列名
     * 只会拼接有 @column 注解的字段
     * @param field
     * @return
     */
    @Override
    public String setKeys(Field field){
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column;
        if (field.isAnnotationPresent(Column.class)) {
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if ("".equals(__column)) {
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            String keysTemp = "<if test=\"__field != null\"> __column, </if>";
            //拼接
            return keysTemp.replaceAll("__field", __field).replaceAll("__column", __column);
        }
        return "";
    }

    /**
     * 替换insert与update的实体类字段, keys的value
     * 只会拼接有 @column 注解的字段
     * @param field
     * @return
     */
    @Override
    public String setValues(Field field){
        if (field.isAnnotationPresent(Column.class)) {
            String valuesTemp = "<if test=\"__field != null\">  #{__field} , </if>";
            return valuesTemp.replaceAll("__field", field.getName());
        }
        return "";
    }

    /**
     * 替换update的 set集合
     * 只会拼接有 @column 注解的字段
     * @param field
     * @return
     */
    @Override
    public String setSets(Field field){
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column;
        String temp = "";
        if(field.isAnnotationPresent(Column.class)) {
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if ("".equals(__column)) {
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            temp = "<if test=\"__field != null\"> __column=#{__field} </if>";
            //拼接
            temp.replaceAll("__field", __field).replaceAll("__column", __column);
        }
        return temp;
    }

    /**
     * 设置需要查询的列名
     * @param field
     * @return
     */
    @Override
    public String setColumns(Field field) {
        String temp = "";
        boolean ignoredColumn = false;
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column = "";
        if (field.isAnnotationPresent(Column.class)) {
            /*有此注解则被忽略*/
            if (field.isAnnotationPresent(IgnoredColumn.class)) {
                ignoredColumn = true;
            }
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
        } else if(field.isAnnotationPresent(Id.class)){
            /*有此注解则被忽略*/
            if (field.isAnnotationPresent(IgnoredColumn.class)) {
                ignoredColumn = true;
            }
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Id.class).name();
        } else {
            ignoredColumn = true;
        }
        if(!ignoredColumn){
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if ("".equals(__column)) {
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            temp = "  __column     __field ,   ";
            temp = temp.replaceAll("__column", __column).replaceAll("__field",__field);
        }
        return temp;
    }

    /**
     * 替换表名
     * @param generics
     * @return
     */
    @Override
    public String setTable(Class<?> generics){
        /* 若未添加注解,直接返回 */
        if(!generics.isAnnotationPresent(Table.class)){
            throw new BaseException("类:"+generics.getName()+"未添加注解 " + Table.class.getName());
        }
        /* 获取注解上的表名 */
        String tableName = generics.getAnnotation(Table.class).name();
        /* 若table注解没有传值,使用类名进行变换 */
        if("".equals(tableName)){
            tableName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, generics.getName());
        }
        /* 替换表名 */
        return tableName;
    }

    /**
     * 替换主键
     * @param field
     * @return
     */
    @Override
    public String setId(Field field){
        String __id = "";
        if (field.isAnnotationPresent(Id.class)) {
            /* 获取注解中表的列名 */
            __id = field.getAnnotation(Id.class).name();
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if("".equals( __id )){
                __id = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName());
            }
        }
        return __id;
    }

    /**
     * 拼接条件查询动态sql
     * @param field
     * @return
     */
    @Override
    public String setConditions(Field field){
        boolean isPass = false;
        String temp = "";
        /* 获取实体类的字段名 */
        String __field = field.getName();
        String __column = "";
        if (field.isAnnotationPresent(Id.class)) {
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Id.class).name();
        } else if(field.isAnnotationPresent(Column.class)){
            /* 获取注解中表的列名 */
            __column = field.getAnnotation(Column.class).name();
        } else {
            /* 没有注解标记的跳过 */
            isPass = true;
        }
        if(!isPass){
            /* 若注解中的值为默认值 "" ,则使用字段名进行转变 */
            if("".equals(__column)){
                __column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, __field);
            }
            temp = "<if test=\"__field != null\"> and __column=#{__field} </if>";
            //拼接
            temp = temp.replaceAll("__field", __field).replaceAll("__column", __column);
        }
        return temp;
    }

    /**
     * 通用替换拼接sql
     * @param generics
     * @param script
     * @return
     */
    public String commonCreateSqlSource(Class<?> generics,String script) {

        StringBuilder id = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        StringBuilder keys = new StringBuilder();
        StringBuilder values = new StringBuilder();
        StringBuilder sets = new StringBuilder();
        StringBuilder conditions = new StringBuilder();

        List<Field> fieldList = getFieldList(generics);
        //遍历所有的属性
        for (Field field : fieldList) {
            if(hasId(script)){
                /* 获取id */
                id.append(setId(field));
            }
            if(hasColumns(script)){
                /* 拼接查询的列名 */
                columns.append(setColumns(field));
            }
            if(hasKeys(script)){
                /* 拼接insert和update的keys */
                keys.append(setKeys(field));
            }
            if(hasValues(script)){
                /* 拼接insert和update的values */
                values.append(setValues(field));
            }
            if(hasSets(script)){
                /* 拼接update的sets */
                sets.append(setSets(field));
            }
            if (hasConditions(script)){
                conditions.append(setConditions(field));
            }
        }
        /* 判断是否需要替换 ${table} 表名不需要遍历 */
        if(hasTable(script)){
            String table = setTable(generics);
            script = script.replaceAll(tablePattern,table);
        }
        /* 判断是否需要替换 ${id} */
        if (hasId(script)){
            script = script.replaceAll(idPattern,id.toString());
        }
        /* 判断是否需要替换 ${columns} */
        if (hasColumns(script)){
            StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
            sb.append(columns);
            sb.append("</trim> ");
            script = script.replaceAll(columnsPattern,sb.toString());
        }
        /* 判断是否需要替换 ${keys} */
        if (hasKeys(script)){
            StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
            sb.append(keys);
            sb.append("</trim> ");
            script = script.replaceAll(keysPattern,sb.toString());
        }
        /* 判断是否需要替换 ${values} */
        if (hasValues(script)){
            StringBuilder sb = new StringBuilder("<trim suffixOverrides=\",\"> ");
            sb.append(values);
            sb.append("</trim> ");
            script = script.replaceAll(valuesPattern,sb.toString());
        }
        /* 判断是否需要替换 ${sets} */
        if (hasSets(script)){
            StringBuilder sb = new StringBuilder("<set> <trim suffixOverrides=\",\"> ");
            sb.append(sets);
            sb.append("</trim> </set>");
            script = script.replaceAll(setsPattern,sb.toString());
        }
        /* 判断是否需要添加查询条件 */
        if (hasConditions(script)){
            StringBuilder sb = new StringBuilder();
            sb.append(conditions);
            script = script.replaceAll(conditionPattern,sb.toString());
        }
        return script;
    }
}
